﻿using MP3Sharp;
using MP3Sharp.Decoding;
using System;
using System.Collections.Generic;


namespace MP3SharpFix
{
    public class Mp3StreamDecoder
    {
        BitStreamClean cleanBit = null;
        public Mp3StreamDecoder(MP3SharpFix.Mp3Data data)
        {

            this.data = data;

            m_Buffer = new BufferFloat(data.Channel);
            m_Decoder = new Decoder(Decoder.DefaultParams);
            m_Decoder.OutputBuffer = m_Buffer;



            if (data.ReadFrameCount == 0)
                throw new Exception("no data");

            var header = data.GetFrame(0);
            cleanBit = new BitStreamClean(header.framedata);
            m_Decoder.DecodeFrame(header, cleanBit);

        }
        MP3SharpFix.Mp3Data data;

        BufferFloat m_Buffer;
        Decoder m_Decoder;

        bool IsEOF = false;
        bool ReadFrame()
        {
            var f = data.ReadNext();
            if (f == null)
            {
                return false;

            }
            cleanBit.data = f.framedata;
            cleanBit.dwordOffset = 0;
            cleanBit.bitOffset = 0;
            m_Decoder.DecodeFrame(f, cleanBit);

            return true;
        }


        public int ReadFloat(float[] data, int offset, int count)
        {
            // Copy from queue buffers, reading new ones as necessary,
            // until we can't read more or we have read "count" bytes
            if (IsEOF)
                return 0;

            int floatRead = 0;
            while (true)
            {
                if (m_Buffer.Left <= 0)
                {
                    if (!ReadFrame()) // out of frames or end of stream?
                    {
                        IsEOF = true;
                        break;
                    }
                }

                // Copy as much as we can from the current buffer:
                floatRead += m_Buffer.Read(data,
                    offset + floatRead,
                    count - floatRead);

                if (floatRead >= count)
                    break;
            }
            return floatRead;

        }
    }
}
